package com.huiquan.homoionym.service;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.huiquan.analysis.domain.User;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.utils.FileUtils;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.RespHeaderUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.homoionym.dao.HomoionymSearchTermsDao;
import com.huiquan.homoionym.dao.HomoionymSearchTermsSubDao;
import com.huiquan.homoionym.domain.HomoionymSearchTerms;
import com.huiquan.homoionym.domain.HomoionymSearchTermsDto;
import com.huiquan.homoionym.domain.HomoionymSearchTermsSub;
import com.huiquan.management.constant.MigrateCode;
import com.huiquan.management.service.MigrateService;

@Service
public class HomoionymSearchTermsService extends BaseService {

	@Autowired
	private HomoionymSearchTermsDao homoionymSearchTermsDao;
	@Autowired
	private HomoionymSearchTermsSubDao homoionymSearchTermsSubDao;
	@Autowired
	private FileUtils fileUtils;

	public ModelAndView list(Integer start, String keyword, String exactSearchFlag,String countPerPageStr) {

		boolean exactFlag = exactSearchFlag != null && exactSearchFlag.equals("1");

		Map<String, Object> param = new HashMap<>();
		if (keyword != null && !keyword.isEmpty()) {
			param.put("keyword", exactFlag ? keyword : "%" + keyword + "%");
		}

		param.put("delFlag", "0");

		int totalSize = homoionymSearchTermsDao.retrieveSize(param);

		Map<String, Integer> pageNo = new HashMap<>();
		if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
			int countPerPage = Integer.parseInt(countPerPageStr);
			pageNo = GetListUtil.getPageNoParam(totalSize, start+"", countPerPage);
			param.put("countPerPage", countPerPage);
		} else {
			pageNo = GetListUtil.getPageNoParam(totalSize, start+"");
		}
		int endPage = pageNo.get("endPage");
		start = pageNo.get("start");
		int startIndex = pageNo.get("startIndex");

		List<HomoionymSearchTerms> list = new ArrayList<>();

		if (startIndex < totalSize) {
			param.put("startIndex", startIndex);
			list = homoionymSearchTermsDao.retrieveList(param);
		}

		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("keyword", "标准词");
		Map<String, String> searchMap = new HashMap<>();
		searchMap.put("keyword", keyword);
		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list,
				searchMap);
		map.put("showSearch", showSearch);
		map.put("showSearchValue", searchMap);
		map.put("exactSearchFlag", exactSearchFlag);
		return new ModelAndView("homoionym/index", map);
	}

	public ModelAndView preEdit(String keyword, String exactSearchFlag, Integer start, String id, User user) {
		String std = "";
		List<String> words = new ArrayList<>();

		// 如果id不为空则表示是修改，否则为新增
		Map<String, Object> map = new HashMap<>();
		if (id != null && !id.isEmpty()) {
			HomoionymSearchTermsDto dto = homoionymSearchTermsDao.retrieveDtoById(Long.parseLong(id));
			std = dto.getStd();
			String[] wordsStr = dto.getWords().split(",");
			Collections.addAll(words, wordsStr);
			words.add("");
		}

		map.put("id", id);
		map.put("start", start);
		map.put("keyword", keyword);
		map.put("exactSearchFlag", exactSearchFlag);
		map.put("std", std);
		map.put("words", words);

		return new ModelAndView("homoionym/search_terms_edit", map);
	}

	public ReturnData edit(Long id, User user, String[] words) {
		// 获取数据库中现有的近义词
		List<HomoionymSearchTermsSub> subs = homoionymSearchTermsSubDao.retrieveListByPid(id);

		// 分成三个列表：添加、删除、修改
		List<String> add = new ArrayList<>();
		for (String word : words) {
			if(!word.isEmpty()) {
				add.add(word);
			}
		}
		List<String> del = new ArrayList<>();
		List<String> upd = new ArrayList<>();

		for (HomoionymSearchTermsSub sub : subs) {
			String word = sub.getWord();
			if (add.contains(word)) {
				// 如果提交数据中存在，则将该数据修改为可用近义词
				add.remove(word);
				if (HomoionymSearchTermsSub.DEL_FLAG_YES.equals(sub.getDelFlag())
						|| HomoionymSearchTermsSub.VERIFY_FLAG_NO.equals(sub.getVerifyFlag())) {
					upd.add(word);
				}
			} else {
				// 如果提交的数据中不存在，则该词将被删除
				del.add(word);
			}
		}

		// 批量添加、删除、修改
		if (!add.isEmpty()) {
			homoionymSearchTermsSubDao.batchInsert(id, add, user.getUserId());
		}
		if (!del.isEmpty()) {
			homoionymSearchTermsSubDao.batchDelete(id, del, user.getUserId());
		}
		if (!upd.isEmpty()) {
			homoionymSearchTermsSubDao.batchUpdate(id, upd, user.getUserId());
		}

		return ReturnUtil.success();
	}

	public ModelAndView delete(Integer start, Long id, String keyword, String exactSearchFlag,
			User user,String countPerPageStr) {
		// 逻辑删除标准词下的近义词
		HomoionymSearchTerms homoionymSearchTerms = new HomoionymSearchTerms();
		homoionymSearchTerms.setId(id);
		homoionymSearchTermsSubDao.delete(homoionymSearchTerms, user.getUserId());

		return list(start, keyword, exactSearchFlag,countPerPageStr);
	}

	public ReturnData searchTermsImport(MultipartFile file, User user) throws Exception {

		InputStream inputStream = null;
		Workbook workbook = null;
		StringBuilder desc = new StringBuilder();
		desc.append("导入成功！\n");

		try {
			// 获取文件流，解析文件
			inputStream = file.getInputStream();

			workbook = new XSSFWorkbook(inputStream);
			Sheet sheet = workbook.getSheetAt(0);

			// 维护数据
			persistData(sheet, user);
			
			// 通过临时表查询excel中是否有多出的标准词
			List<String> stdList = homoionymSearchTermsDao.retrieveMoreStdList();
			if(!stdList.isEmpty()) {
				desc.append("excel比系统中多出的标准词：");
				for(String std:stdList) {
					desc.append(std);
					desc.append(",");
				}
			}

			// 备份上传文件
			String fileName = "search_terms" + System.currentTimeMillis() + ".xlsx";
			fileUtils.backupImportFile(file, "homoionym", fileName);

		} catch (Exception e) {
			throw e;
		} finally {
			workbook.close();
			inputStream.close();
		}
		ReturnData rd = ReturnUtil.success();
		rd.getReturnCode().setDesc(desc.toString());
		return rd;
	}

	/**
	 * 维护数据
	 * 
	 * @param sheet
	 */
	private void persistData(Sheet sheet, User user) {
		Map<String, String> groupMap = new HashMap<>();

		// 将excel中的数据组装后维护到bas_temp_homoionym_search_original
		for (Row row : sheet) {
			String std = "";
			String word = "";
			for (int i = 0; i < row.getLastCellNum(); i++) {
				if (i == 0) {
					std = row.getCell(i).getStringCellValue().trim();
				} else {
					word = row.getCell(i).getStringCellValue().trim();
					if (!word.isEmpty()) {
						if (groupMap.get(std) != null && !groupMap.get(std).isEmpty()) {
							groupMap.put(std, groupMap.get(std) + "," + word);
						} else {
							groupMap.put(std, word);
						}
					}
				}
			}
		}

		initialOriginal(groupMap);

		// 将数据维护到正式数据
		homoionymSearchTermsDao.persistCheckedDataByTemp(user);
	}

	private void initialOriginal(Map<String, String> groupMap) {
		// 先清空临时表
		homoionymSearchTermsDao.clearOriginal();

		List<Map<String, String>> list = new ArrayList<>();
		for (String std : groupMap.keySet()) {
			Map<String, String> data = new HashMap<>();
			data.put("std", std);
			data.put("word", "," + groupMap.get(std) + ",");
			list.add(data);

			if (list.size() == 1000) {
				homoionymSearchTermsDao.insertOriginal(list);
				list.clear();
			}
		}

		if (list.size() > 0) {
			homoionymSearchTermsDao.insertOriginal(list);
		}
	}

	public void searchTermsExport(HttpServletResponse resp) {

		// 获取dto
		List<HomoionymSearchTermsDto> dtos = homoionymSearchTermsDao.retrieveUncheckedDtoList();

		// 将获取的近义词数据放置在list中
		Map<String, List<String>> data = new HashMap<>();
		List<String> words = null;
		for (HomoionymSearchTermsDto dto : dtos) {
			words = data.get(dto.getStd());
			if (words != null) {
				words.add(dto.getWords());
			} else {
				words = new ArrayList<>();
				words.add(dto.getStd());
				words.add(dto.getWords());
				data.put(dto.getStd(), words);
			}
		}

		// 设置respons的头信息
		RespHeaderUtil.setXlsxResp(resp, "未校验近义词");

		// 创建文档
		XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
		Sheet sheet = xssfWorkbook.createSheet("近义词"); // 创建Sheet

		// 循环写入数据
		int i = 0;
		Row row = null;
		for (List<String> rowWords : data.values()) {
			row = sheet.createRow(i);
			addCell(row, rowWords);
			i++;
		}
		LOGGER.info("codeExport create excel success!");

		OutputStream os = null;
		try {
			os = resp.getOutputStream();
			xssfWorkbook.write(os);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				xssfWorkbook.close();
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private void addCell(Row row, List<String> cellValues) {
		if (cellValues.size() > 0) {
			Cell cell = null;
			for (int i = 0; i < cellValues.size(); i++) {
				String cellValue = cellValues.get(i);
				cell = row.createCell(i);
				cell.setCellValue(cellValue);
			}
		}
	}

	public ReturnData searchTermsExpansionData(MultipartFile file, User user) throws Exception {

		// 获取文件流，解析文件
		InputStreamReader isr = new InputStreamReader(file.getInputStream(), "UTF-8");
		BufferedReader br = new BufferedReader(isr);
		String line = null;
		Map<String, String> groupMap = new HashMap<>();
		String std = "";
		String word = "";
		while ((line = br.readLine()) != null) {
			if (line.split("\t").length > 1) {

				std = line.split("\t")[0].trim();
				word = line.split("\t")[1].trim();

				if (!word.isEmpty()) {
					if (word.endsWith(",")) {
						word = word.substring(0, word.length() - 1);
					}
					if (groupMap.get(std) != null && !groupMap.get(std).isEmpty()) {
						groupMap.put(std, groupMap.get(std) + "," + word);
					} else {
						groupMap.put(std, word);
					}
				}
			}
		}
		isr.close();
		br.close();

		initialOriginal(groupMap);

		// 将数据维护到正式数据
		homoionymSearchTermsDao.persistUncheckedDataByTemp(user);

		// 备份上传文件
		String fileName = "expansion_search_terms" + System.currentTimeMillis() + ".txt";
		fileUtils.backupImportFile(file, "homoionym", fileName);

		return ReturnUtil.success();
	}

	public void searchTermsCheckedExport(HttpServletResponse resp) {

		// 获取dto
		List<HomoionymSearchTermsDto> dtos = homoionymSearchTermsDao.retrieveCheckedDtoList();

		// 将获取的近义词数据放置在list中
		StringBuilder sb = new StringBuilder();
		for (HomoionymSearchTermsDto dto : dtos) {
			sb.append(dto.getStd());
			sb.append("\t");
			sb.append(dto.getWords());
			sb.append("\n");
		}

		// 设置respons的头信息
		RespHeaderUtil.setTxtResp(resp, "已校验近义词");

		OutputStream os = null;
		BufferedOutputStream buff = null;
		try {
			os = resp.getOutputStream();
			buff = new BufferedOutputStream(os);
			byte[] byt = sb.toString().getBytes("UTF-8");
			buff.write(byt);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				buff.flush();
				buff.close();
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void physicalDelete(String std) {
		homoionymSearchTermsDao.physicalDelete(std);
	}
	
	@Autowired
	private MigrateService migrateService;

	public void migrateHomoionym() throws Exception {

		List<Map<String, String>> stdAndWordList = homoionymSearchTermsDao.retrieveStdAndWord();

		StringBuffer sb = new StringBuffer();
		for (Map<String, String> stdAndWord : stdAndWordList) {
			sb.append(stdAndWord.get("std"));
			sb.append((char) 1);
			sb.append(stdAndWord.get("word"));
			sb.append("\n");
		}

		migrateService.migrateHiveByCodeAndString(MigrateCode.HOMOIONYM_SEARCH, sb.toString());
	}
}
